﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;

namespace eslib.xml
{
    public class XmlConfigReader
    {
        private XmlDocument doc = null;

        public XmlConfigReader()
        {
            doc = new XmlDocument();
        }


        /// <summary>
        /// 打开xml配置文件,并返回其根节点对象
        /// </summary>
        /// <param name="xmlPath"></param>
        /// <returns></returns>
        public XmlConfigItem Open(string xmlPath)
        {
            doc.Load(xmlPath);
            return GetRoot();
        }

        /// <summary>
        /// 打开xml配置文件,并返回其根节点对象
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public XmlConfigItem Open(Stream stream)
        {
            doc.Load(stream);
            return GetRoot();
        }

        /// <summary>
        /// 打开xml源，并返回其节点对象
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public XmlConfigItem OpenXmlString(string source)
        {
            doc.Load(new StringReader(source));
            return GetRoot();
        }


        #region 内部方法

        XmlConfigItem GetRoot()
        {
            return FillConfigItem(doc.DocumentElement);
        }



        XmlConfigItem FillConfigItem(XmlElement ele)
        {
            XmlConfigItem item = new XmlConfigItem(ele.Name);

            //属性集
            item.Attributes = GetAttributes(ele);

            //子集
            if (HasChild(ele))
                item.Children = GetChildren(item, ele);

            return item;
        }




        List<XmlKeyValue> GetAttributes(XmlElement ele)
        {
            List<XmlKeyValue> attrColl = new List<XmlKeyValue>();

            foreach (XmlAttribute attr in ele.Attributes)
            {
                XmlKeyValue kv = new XmlKeyValue();
                kv.AttributeName = attr.Name;
                kv.AttributeValue = attr.Value;
                attrColl.Add(kv);
            }

            return attrColl;
        }



        bool HasChild(XmlElement ele)
        {
            return ele.ChildNodes.Count > 0;
        }



        List<XmlConfigItem> GetChildren(XmlConfigItem parent, XmlElement ele)
        {
            List<XmlConfigItem> children = new List<XmlConfigItem>();

            foreach (XmlNode node in ele.ChildNodes)
            {
                if (node.NodeType == XmlNodeType.Element)
                {
                    XmlElement child = (XmlElement)node;
                    children.Add(FillConfigItem(child));
                }
                else if (node.NodeType == XmlNodeType.Text)
                {
                    parent.Text = node.Value;
                }
            }

            return children;
        }


        #endregion
    }
}
